﻿using JunionRobotTaskManager.Repository;
using Newtonsoft.Json;
using SqlSugar;
using System.ComponentModel;

namespace JunionRobotTaskManager.Models
{
   
    /// <summary>
    /// 任务
    /// </summary>
    public class Job
    {
        

        #region 属性

        /// <summary>
        /// 任务Id
        /// </summary>
        [SugarColumn(IsPrimaryKey = true)]
        public string Id { get; set; }


        #region 时间

        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime CreateTime { get; set; }


        /// <summary>
        /// 开始执行时间
        /// </summary>
        [SugarColumn(IsNullable = true)]
        public DateTime? BeginTime { get; set; }


        /// <summary>
        /// 任务更新时间
        /// </summary>
        [SugarColumn(IsNullable = true)]
        public DateTime? UpdateTime { get; set; }

        #endregion

        /// <summary>
        /// 任务状态
        /// </summary>
        public TaskState Status { get; set; }

        /// <summary>
        /// 任务优先级
        /// </summary>
        public int Priority { get; set; }

        /// <summary>
        /// 任务目标点
        /// </summary>
        [SqlSugar.SugarColumn(ColumnDataType = "text", IsJson = true)]
        public Dictionary<string,string> Targets { get; set; }


        /// <summary>
        /// 任务物料号
        /// </summary>
        [SqlSugar.SugarColumn(ColumnDataType = "text", IsJson = true, IsNullable = true)]
        public string[] MaterialCodes{ get; set; }


        /// <summary>
        /// 任务类型 1.接料任务,2.送料任务,3.复合任务, 4.充电任务
        /// </summary>
        public TaskType Type { get; set; }


        /// <summary>
        /// 备用字段
        /// </summary>
        public string Remark { get; set; } = "";

        /// <summary>
        /// 分配机器人的ID
        /// </summary>
        [SugarColumn(IsNullable = true)]
        public string RobotId { get; set; } //机器人IP

        /// <summary>
        /// 指定的机器人序列
        /// </summary>
        [SqlSugar.SugarColumn(ColumnDataType = "text", IsJson = true, IsNullable = true)]
        public string[] AssignRobots { get; set; }

        /// <summary>
        /// 机器人最近的一个对接位置编号
        /// </summary>

        [SqlSugar.SugarColumn(IsNullable = true)]
        public  string  CurrentPosition { get; set; }

        /// <summary>
        /// 任务序列号,通过这个索引在哪个位置在进行
        /// </summary>
       
        public int JobIndex { get; set; }

        /// <summary>
        /// 机器人下一个位置点
        /// </summary>

        [SqlSugar.SugarColumn(IsNullable = true)]
        public string CurrentTarget 
        {
             get
             {
                if(JobIndex>= Targets.Keys.Count)
                    return Targets.Keys.ToArray().Last();
                else
                    return Targets.Keys.ToArray()[JobIndex];

            }
        }
        #endregion

        #region Navigation


        [SugarColumn(IsIgnore = true)]
        public Robot AssignRobot { get; set; }//分配的机器人


       

        #endregion


        #region Override

        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return false;
            }
            if (ReferenceEquals(obj, this))
            {
                return true;
            }
            if (obj.GetType() != GetType())
            {
                return false;
            }
            return obj is Job b && b.Id == Id;

        }

        public override int GetHashCode()
        {
            return Id.GetHashCode();
        }

        public override string ToString()
        {

            return $"Job Info Is:Id({Id}),TaskType:{Type},TaskState:{Status}, BeginTime({BeginTime?.ToString("MM-dd HH:mm:ss") ?? ""}),UpdateTime({UpdateTime?.ToString("MM-dd HH: mm: ss") ?? ""}),Target:{JsonConvert.SerializeObject(Targets)??"null"}";
        }

        #endregion

        #region Method

        /// <summary>
        /// 更新任务信息
        /// </summary>
        /// <param name="jobRepoitory"></param>
        /// <param name="isAbort">是否打断默认是false</param>
        /// <returns></returns>
        public bool UpdateInfo(IJobRepoitory jobRepoitory, TaskState taskState)
        {

            if (taskState == TaskState.BeforeGet|| TaskState.BeforePut == taskState)
            {
                if (BeginTime == null)
                    BeginTime = DateTime.Now;
            }
            Status = taskState;
            UpdateTime = DateTime.Now;
            
            bool result= jobRepoitory.UpdateEntity(this);
            


            return result;
        }
       
        /// <summary>
        /// 更改状态
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public Job ChangeStatus(string msg)
        {
          
            if (msg.Contains("arrived"))
            {
     
                Status = Targets[CurrentTarget].ToLower() == "put" ?  TaskState.Puting: TaskState.Geting ;
            }
            else if (msg.Contains("finished"))
            {
               
                if (Type == TaskType.PickUp)
                {
                    if(JobIndex<Targets.Count())
                    {

                        Status = Targets[CurrentTarget].ToLower() == "put" ? TaskState.BeforePut : TaskState.BeforeGet;
                    }
                    else
                    {
                        Status = TaskState.Complete;
                       
                       
                    }


                }
                else
                {
                    Status= TaskState.Complete;
                }
            }
            else if (msg == "resume")
            {
                
                if (Type == TaskType.PickUp)
                {
                    Status = (Status == TaskState.Geting|| Status == TaskState.Getted) ? TaskState.Getted : TaskState.Complete;
                }
                else
                {
                    Status = TaskState.Complete;
                }
            }
            else if(msg=="cancel")
            {
                Status= TaskState.Canceled;
            }
            else if (msg == "abort")
            {
                Status = TaskState.Abort;
            }

            return this;
        }

        public static Job GetChargeJob(string robot,Dock dock)
        {
            var targets = new Dictionary<string, string>();

            targets.Add(dock.Id, "Put");
            return new Job()
            {
                Id = Guid.NewGuid().ToString("N"),
                CreateTime = DateTime.Now,
                BeginTime = DateTime.Now,
                UpdateTime = DateTime.Now,
                Priority = 0,
                Targets = targets,
                Type = TaskType.Charge,
                Status = TaskState.Charging,
                RobotId = robot
            };
        }

        public bool AssignInfoRecord(IServiceScope scope,Robot robot)
        {


            RobotId = robot.Id;
            robot.CurrentJob = this;
            robot.JobId = Id;
            robot.IsAvailable = false;


            IRobotRepository robotRepository = scope.ServiceProvider.GetService<IRobotRepository>();
            var isRobotUpdated =  robotRepository.UpdateEntity(robot);
            IJobRepoitory jobRepository = scope.ServiceProvider.GetService<IJobRepoitory>();
            var state = Type == TaskType.Put ? TaskState.BeforePut : TaskState.BeforeGet;
            return isRobotUpdated && UpdateInfo(jobRepository, state);
        }
        #endregion
       

    }


    public enum TaskState
    {
        [Description("等待执行")]
        Pending = 0,
        [Description("接料前")]
        BeforeGet,
        [Description("接料中")]
        Geting,
        [Description("接料完成")]
        Getted,
        [Description("送料前")]
        BeforePut,
        [Description("送料中")]
        Puting,
        [Description("执行中")]
        Excuting,
        [Description("正常完成")]
        Complete,
        [Description("意外打断")]
        Abort,
        [Description("被取消")]
        Canceled,
        [Description("充电中")]
        Charging,

    }


    public enum TaskType
    {
        [Description("接料任务")]
        Get = 1,
        [Description("送料任务")]
        Put = 2,
        [Description("接送料任务")]
        PickUp = 3,
        [Description("充电任务")]
        Charge = 4,
    }
}
